/**
 * 
 */
package com.easidea.tim.dao.finance;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.LockModeType;

import org.apache.log4j.Logger;
import org.hibernate.Criteria;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springside.core.dao.extend.HibernateEntityExtendDao;

import com.easidea.tim.dao.customer.CustomerDao;
import com.easidea.tim.entity.customer.Customer;
import com.easidea.tim.entity.finance.CustomerAccountListing;
import com.easidea.tim.entity.finance.FinanceItem;

/**
 * @author Harrison
 *
 */
public class CustomerAccountListingDao extends HibernateEntityExtendDao<CustomerAccountListing> {
	
	private CustomerDao customerDao;
	private FinanceItemDao financeItemDao;
	
	private static final Logger log = Logger.getLogger(CustomerAccountListingDao.class);
	
	
	/**
	 * 登记财务数据
	 * 
	 * 
	 * @param custId
	 * @param financeItemId
	 * @param memoAndAmountMap
	 * @param operator
	 * @return
	 */
	public boolean bookingFinanceData(Long custId, Long financeItemId, Map<String, Object> memoAndAmountMap, String operator){
		boolean t=false ,hasError = false;
		
		if(custId == null){
			hasError = true;
			log.error(" Booking finance error : custId is null");
		}
		
		if(financeItemId == null){
			hasError = true;
			log.error(" Booking finance error : financeItemId is null");
		}
		
		if(memoAndAmountMap != null){
			if(!memoAndAmountMap.containsKey("memo")){
				hasError = true;
				log.error(" Booking finance error : can not obtain the memo data");
			}else if (!memoAndAmountMap.containsKey("amountsummary")) {
				hasError = true;
				log.error(" Booking finance error : can not obtain the amountsummary data");
			}
		}else{
			hasError = true;
			log.error(" Booking finance error : memoAndAmountMap is null");
		}
		// 数据校验
		
		if(!hasError){
			CustomerAccountListing cal = new CustomerAccountListing();
			Customer tempCust = new Customer();
			tempCust.setId(custId);
			cal.setCustomer(tempCust);
			// 客户信息

			FinanceItem tempFI = new FinanceItem();
			tempFI.setId(financeItemId);
			cal.setItem(tempFI);
			// 财务科目信息
			
			String memo = (String) memoAndAmountMap.get("memo");
			Double amountSummary = (Double) memoAndAmountMap.get("amountsummary");
			cal.setMemo(memo);
			cal.setAmount(amountSummary);
			cal.setCreator(operator);
			cal.setModifier(operator);
			t = addCustomerAccoutListing(cal);
			if(t)
				log.warn(" Booking finance success, customerId: " + custId + " financeItemId: " + financeItemId 
					+ " memo: " + memo + " amount: " + amountSummary);
		}
		
		return t;
	}
	
	
	@SuppressWarnings("unchecked")
	public List<CustomerAccountListing> getNewCustomerListing(Long customerId){
		Criteria cte = this.createUnDeletedCriteria();
		cte.add(Restrictions.eq("customer.id", customerId));
		cte.addOrder(Order.desc("modifyTime"));
		cte.setMaxResults(1);
		return cte.list();
		
	}

	/**
	 * 添加数据
	 * 
	 * @param cal
	 * @return
	 */
	public boolean addCustomerAccoutListing(CustomerAccountListing cal) {
		boolean t = false;
		if (cal != null && cal.getCustomer() != null
				&& cal.getCustomer().getId() != null && cal.getItem() != null
				&& cal.getItem().getId() != null && cal.getAmount() != null) {
			
			cal.setId(null); // 清理flex的默认数据
			
			Customer customer = customerDao.get(cal.getCustomer().getId());
			FinanceItem fi = financeItemDao.get(cal.getItem().getId());
			if (fi != null) {
				cal.setItem(fi);
				cal.setItemName(fi.getName());
			} else {
				log.error(" Booking finance error, finance item does not exists with id : " + cal.getItem().getId());
				return t;
			}

			if (customer != null) {
				log.warn(" prepare to save customer finance data with customer Id: " + customer.getId());
				List calist = this.getNewCustomerListing(customer.getId());
				double accountSummary = 0;
				if(calist!=null&&calist.size()>0){
					CustomerAccountListing ca = (CustomerAccountListing)calist.get(0);
					accountSummary = ca.getTotalAmount();
				}else{
					accountSummary = customer.getAccountSummary();
				}
				cal.setCustomer(customer);
				cal.setCustomerName(customer.getName());
				cal.setLastAmount(accountSummary);
				cal.setAmount(cal.getAmount()*(cal.getItem().getDirection() > 0? 1 : -1)); //转换正负数
				
				Double summary = accountSummary + cal.getAmount();
				cal.setTotalAmount(summary);
				
				String logMsg = " customer: " + cal.getCustomerName() + ", lastAmount: " + cal.getLastAmount()
					+ ", currentAmount: " + cal.getAmount() + ", newlyTotalAmount: " + cal.getTotalAmount();
			
				customer.setAccountSummary(summary);
				customer.setModifyTime(new Date()); // 客户数据的修改日期，监控数据是否在同一时间被更新

//				customerDao.merge(customer); //强制同步客户数据
				customerDao.getHibernateTemplate().update(customer); //改merge为update
				this.save(cal);//保存
				
				if(customer.getAccountSummary().equals(summary)){
					t = true;
					log.warn(" Booking finance successfully , new cal id is : " + cal.getId() 
							+ " and the message is : " + logMsg + "; current customer total_amount: " + accountSummary 
							+ " and newly modified time : " + customer.getModifyTime());
				}else{
					t = false;
					log.error(" Booking finance failure with the data : " + logMsg);
				}
			} else {
				log.error(" Booking finance error, customer does not exists with id : " + cal.getCustomer().getId());
				return t;
			}
		}else
			log.error(" Booking finance error : customerId or finance item Id or amount is null ~!");
		return t;
	}

	/**
	 * @return the customerDao
	 */
	public CustomerDao getCustomerDao() {
		return customerDao;
	}

	/**
	 * @param customerDao the customerDao to set
	 */
	public void setCustomerDao(CustomerDao customerDao) {
		this.customerDao = customerDao;
	}

	/**
	 * @return the financeItemDao
	 */
	public FinanceItemDao getFinanceItemDao() {
		return financeItemDao;
	}

	/**
	 * @param financeItemDao the financeItemDao to set
	 */
	public void setFinanceItemDao(FinanceItemDao financeItemDao) {
		this.financeItemDao = financeItemDao;
	}
	
}
